home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 037a / ratl10.zip / RATTLE.PAS < prev    next >
Pascal/Delphi Source File  |  1991-10-23  |  20KB  |  583 lines

  1. program Rattle;
  2.  
  3. {
  4.   Program:            RATTLE.PAS
  5.   Version:            1.0
  6.   Creation Date:      October 9, 1991
  7.   Modification Date:  October 23, 1991
  8.   Operating System:   MS-DOS 3.x and Windows 3.0
  9.   Hardware Reguired:  Windows-capable computer system
  10.   Programming System: Turbo Pascal for Windows 1.0
  11.   Author:             Craig Boyd
  12.   Ownership:          Copyright 1991 by Craig Boyd
  13.                       All rights reserved
  14.  
  15.   About This Program
  16.  
  17.   Rattle (as in "Shake Rattle 'n Roll") allocates and deallocates blocks
  18.   of memory in a random fashion, stress-testing other running Windows
  19.   applications by subjecting them to adverse and quickly changing memory
  20.   conditions.  Rattle is functionally equivalent to Shaker, a utility
  21.   shipped with the Microsoft Windows Software Development Kit (SDK).  That
  22.   is, it's as functionally equivalent as I can make it without ever laying
  23.   eyes on Shaker or its source code.  My program is based on descriptions
  24.   of the Shaker algorithm obtained from SDK owners.  Plus it has other
  25.   goodies that are all mine.  See the RATTLE.WRI file for complete usage
  26.   and compilation instructions.  Enjoy.
  27.  
  28.  
  29.   Update History
  30.  
  31.   update    ver   description (author)
  32.   -------   ---   -----------
  33.   9110.09   0.0   Work begun. (CSB)
  34.   9110.11   0.0   Yay, we have a working app! (CSB)
  35.   9110.14   0.0   Added status display to AboutBox. (CSB)
  36.   9110.15   0.0   Fixed checkbox bug. (CSB)
  37.   9110.20   0.0   Added icon animation. (CSB)
  38.   9110.21   0.0   Added spacer memory blocks option. (CSB)
  39.   9110.23   1.0   Added 0 timer option to use Rattle as a memory hog.
  40.                   Added option to save settings in WIN.INI.
  41.                   First release uploaded to CompuServe. (CSB)
  42. }
  43.  
  44. uses
  45.   Strings,
  46.   WinTypes,
  47.   WinProcs,
  48.   WObjects;
  49.  
  50. {$R-}
  51.  
  52. {$R Rattle}
  53.  
  54. {-- Global Declarations -------------------------------------------------}
  55.  
  56. const
  57.   AppName : pchar = 'Rattle';
  58.  
  59.   id_BlockSize  = 101;                                     { control IDs }
  60.   id_BlockCount = 102;
  61.   id_TimerFreq  = 103;
  62.   id_Sound      = 104;
  63.   id_Minimize   = 105;
  64.   id_Animate    = 106;
  65.   id_Spacers    = 107;
  66.  
  67.   id_ShakeIt      = 201;                                       { buttons }
  68.   id_StopIt       = 202;
  69.   id_Reset        = 203;
  70.   id_SaveSettings = 204;
  71.  
  72.   sc_About = 901;                    { system menu command for About box }
  73.  
  74.   id_Status = 101;                         { static control in About box }
  75.  
  76.   BlockFrac = 4;            { size of spacer block: 4 = 1/4 of BlockSize }
  77.   Tick      = true;
  78.   Tock      = false;
  79.  
  80. type
  81.   TMyApp = object(TApplication)
  82.     procedure InitMainWindow; virtual;
  83.   end;
  84.  
  85.   PBlockCollection = ^TBlockCollection;
  86.   TBlockCollection = object(TCollection)
  87.     procedure FreeItem(Item : pointer); virtual;
  88.   end;
  89.  
  90.   PRattleSettings = ^TRattleSettings;
  91.   TRattleSettings = record
  92.     BlockSize,                          { size of memory blocks in bytes }
  93.     BlockCount,                                   { max number of blocks }
  94.     TimerFreq  : longint;            { seconds between block allocations }
  95.     MakeSound,                            { true to beep when allocating }
  96.     Minimize,                             { true to minimize on start up }
  97.     Animate,                         { true to change icon on timer tick }
  98.     Spacers    : boolean;               { true to allocate spacer blocks }
  99.   end;
  100.  
  101.   PRattleDlg = ^TRattleDlg;
  102.   TRattleDlg = object(TDlgWindow)
  103.     Settings,
  104.     StartSettings  : TRattleSettings;
  105.     EditBlockSize,
  106.     EditBlockCount,
  107.     EditTimerFreq  : PEdit;
  108.     ToggleSound,
  109.     ToggleMinimize,
  110.     ToggleAnimate,
  111.     ToggleSpacers  : PCheckBox;
  112.     Blocks         : PBlockCollection;                   { memory blocks }
  113.     Icon1,
  114.     Icon2          : hIcon;
  115.     IconState,
  116.     Running        : boolean;                 { true if timer is running }
  117.     constructor Init(AParent      : PWindowsObject;
  118.                      AName        : pchar;
  119.                      InitSettings : TRattleSettings);
  120.     destructor Done; virtual;
  121.     procedure SetUpWindow; virtual;
  122.     function GetClassName : pchar; virtual;
  123.     procedure GetWindowClass(var AWndClass: TWndClass); virtual;
  124.     procedure WMSysCommand(var Msg : TMessage);
  125.       virtual wm_First + wm_SysCommand;
  126.     procedure WMTimer(var Msg : TMessage);
  127.       virtual wm_First + wm_Timer;
  128.     procedure ShakeIt(var Msg : TMessage);        { start allocating RAM }
  129.       virtual id_First + id_ShakeIt;
  130.     procedure StopIt(var Msg : TMessage);    { stop program, release RAM }
  131.       virtual id_First + id_StopIt;
  132.     procedure Reset(var Msg : TMessage);      { restore startup settings }
  133.       virtual id_First + id_Reset;
  134.     procedure SaveSettings(var Msg : TMessage);  { save setup in WIN.INI }
  135.       virtual id_First + id_SaveSettings;
  136.     procedure ResetParams;                    { restore startup settings }
  137.     function GetSettings : boolean;           { get values from controls }
  138.     procedure ReadSettings;                    { read setup from WIN.INI }
  139.     procedure Error(Msg : pchar);
  140.   end;
  141.  
  142.   PAboutDialog = ^TAboutDialog;
  143.   TAboutDialog = object(TDialog)
  144.     BlockSize,
  145.     Blocks    : longint;
  146.     constructor Init(AParent        : PWindowsObject;
  147.                      AName          : pchar;
  148.                      InitBlockSize,
  149.                      InitBlockCount : longint);
  150.     procedure SetupWindow; virtual;
  151.   end;
  152.  
  153.   TNumStr = array[0..6] of char;
  154.  
  155. const
  156.   { Program defaults, if none specified in WIN.INI }
  157.   DefSettings : TRattleSettings = (
  158.     BlockSize  : 8192;
  159.     BlockCount : 20;
  160.     TimerFreq  : 5;
  161.     MakeSound  : false;
  162.     Minimize   : true;
  163.     Animate    : true;
  164.     Spacers    : false);
  165.  
  166. {-- Global Procedures ---------------------------------------------------}
  167.  
  168. procedure BoolToStr(B : boolean;
  169.                     S : pchar);
  170. {
  171.   Converts the boolean value B into a string ('1' or '0') and stores
  172.   it in the character array pointed to by S.
  173. }
  174.   begin
  175.     if B then strcopy(S,'1') else strcopy(S,'0');
  176.   end { BoolToStr };
  177.  
  178. {-- TRattleDlg Methods --------------------------------------------------}
  179.  
  180. constructor TRattleDlg.Init;
  181.   begin
  182.     TDlgWindow.Init(AParent,AName);
  183.     StartSettings := InitSettings;
  184.     ReadSettings;
  185.     Blocks := nil;
  186.     Running := false;
  187.     IconState := Tock;
  188.     randomize;
  189.     EditBlockSize := new(PEdit,InitResource(@Self,id_BlockSize,sizeof(TNumStr)));
  190.     EditBlockCount := new(PEdit,InitResource(@Self,id_BlockCount,sizeof(TNumStr)));
  191.     EditTimerFreq := new(PEdit,InitResource(@Self,id_TimerFreq,sizeof(TNumStr)));
  192.     ToggleSound := new(PCheckBox,InitResource(@Self,id_Sound));
  193.     ToggleMinimize := new(PCheckBox,InitResource(@Self,id_Minimize));
  194.     ToggleAnimate := new(PCheckBox,InitResource(@Self,id_Animate));
  195.     ToggleSpacers := new(PCheckBox,InitResource(@Self,id_Spacers));
  196.   end { TRattleDlg.Init };
  197.  
  198. destructor TRattleDlg.Done;
  199.   begin
  200.     if Running then KillTimer(HWindow,1);
  201.     if Blocks <> nil then dispose(Blocks,Done);
  202.     TDlgWindow.Done;
  203.   end { TRattleDlg.Done };
  204.  
  205. procedure TRattleDlg.SetUpWindow;
  206.   var
  207.     SysMenu : hMenu;
  208.   begin
  209.     TDlgWindow.SetUpWindow;
  210.  
  211.     { Add About option to system menu }
  212.     SysMenu := GetSystemMenu(hWindow,false);
  213.     AppendMenu(SysMenu,mf_separator,0,nil);
  214.     AppendMenu(SysMenu,mf_String,sc_About,'&About...');
  215.  
  216.     { Set default parameters }
  217.     ResetParams;
  218.   end { TRattleDlg.SetUpWindow };
  219.  
  220. function TRattleDlg.GetClassName;
  221.   begin
  222.     GetClassName := AppName;
  223.   end { TRattleDlg.GetClassName };
  224.  
  225. procedure TRattleDlg.GetWindowClass;
  226.   begin
  227.     TDlgWindow.GetWindowClass(AWndClass);
  228.     Icon1 := LoadIcon(HInstance,'Rattle1');
  229.     Icon2 := LoadIcon(HInstance,'Rattle2');
  230.     AWndClass.hIcon := Icon1;
  231.   end { TRattleDlg.GetWindowClass };
  232.  
  233. procedure TRattleDlg.WMSysCommand;
  234.   var
  235.     Dlg   : PAboutDialog;
  236.     Count : longint;
  237.   begin
  238.     if Msg.wParam = sc_About then begin
  239.       if Blocks = nil then
  240.         Count := 0
  241.       else
  242.         Count := Blocks^.Count;
  243.       new(Dlg,Init(@Self,'AboutBox',Settings.BlockSize,Count));
  244.       Application^.ExecDialog(Dlg);
  245.     end;
  246.     DefWndProc(Msg);
  247.   end { TRattleDlg.WMSysCommand };
  248.  
  249. procedure TRattleDlg.WMTimer(var Msg : TMessage);
  250. {
  251.   Responds to a wm_Timer message by adding a memory block to the Blocks
  252.   collection.  The collection is not allowed to grow beyond the value set
  253.   by BlockCount.  If the Blocks collection is full, then a memory block
  254.   is chosen at random and deleted.  The collection never has more than
  255.   BlockCount items and never consumes more than BlockCount * BlockSize
  256.   bytes of memory.
  257.  
  258.   We also check the Spacers flag before allocating a block.  If true,
  259.   we temporarily allocate a small block of memory before adding a block
  260.   to our collection, then release the temporary block.  This causes even
  261.   more heap fragmentation.
  262.  
  263.   We also perform a couple of steps to make the program a little more fun
  264.   to use.  Sillier, maybe, but definitely more fun.  First, if the
  265.   MakeSound flag is set, we call MessageBeep.  Second, if our window is
  266.   minimized and the Animate flag is set, we toggle the icon.  These two
  267.   extra steps give you an audible and/or visual cue as to what Rattle is
  268.   up to.
  269.  
  270.   This method is not called if TimerFreq is set to zero.
  271. }
  272.   var
  273.     P,
  274.     Spacer : PHandle;
  275.   begin
  276.     with Settings do begin
  277.       if MakeSound then MessageBeep(0);
  278.       if (Animate) and (IsIconic(HWindow)) then begin
  279.         case IconState of
  280.           Tick : SetClassWord(HWindow,gcw_HIcon,Icon1);
  281.           Tock : SetClassWord(HWindow,gcw_HIcon,Icon2);
  282.         end;
  283.         IconState := not IconState;
  284.         InvalidateRect(HWindow,nil,true);
  285.       end;
  286.  
  287.       if Blocks^.Count = BlockCount then
  288.         Blocks^.AtFree(random(BlockCount))         { free a memory block }
  289.       else
  290.         begin
  291.           if Spacers then begin
  292.             new(Spacer);
  293.             Spacer^ := GlobalAlloc(gmem_Fixed,BlockSize div BlockFrac);
  294.             GlobalLock(Spacer^);
  295.           end;
  296.           new(P);                                         { get a handle }
  297.           P^ := GlobalAlloc(gmem_Fixed,BlockSize);    { grab some memory }
  298.           if P^ <> 0 then begin
  299.             GlobalLock(P^);                                    { lock it }
  300.             Blocks^.Insert(P);                { add handle to collection }
  301.           end;
  302.           if Spacers then begin
  303.             GlobalUnlock(Spacer^);
  304.             GlobalFree(Spacer^);
  305.             dispose(Spacer);
  306.           end;
  307.         end;
  308.     end;
  309.   end { TRattleDlg.WMTimer };
  310.  
  311. procedure TRattleDlg.ShakeIt;
  312.   var
  313.     P : PHandle;
  314.     I : integer;
  315.   begin
  316.     if not GetSettings then exit;                    { read the controls }
  317.     with Settings do begin
  318.       if TimerFreq = 0 then              { create collection and fill it }
  319.         begin
  320.           Blocks := new(PBlockCollection,Init(BlockCount,0));
  321.           for I := 1 to BlockCount do begin
  322.             new(P);                                       { get a handle }
  323.             P^ := GlobalAlloc(gmem_Fixed,BlockSize);  { grab some memory }
  324.             if P^ <> 0 then begin
  325.               GlobalLock(P^);                                  { lock it }
  326.               Blocks^.Insert(P);              { add handle to collection }
  327.             end;
  328.           end;
  329.           if MakeSound then MessageBeep(0);
  330.         end
  331.       else
  332.         begin
  333.           if SetTimer(HWindow,1,TimerFreq * 1000,nil) = 0 then begin
  334.             Error('No free timers');
  335.             exit;
  336.           end;
  337.           Running := true;
  338.           Blocks := new(PBlockCollection,Init(BlockCount,0));
  339.         end;
  340.       { Disable all controls except Quit button, enable Stop It! button }
  341.       EnableWindow(GetItemHandle(id_BlockSize),false);
  342.       EnableWindow(GetItemHandle(id_BlockCount),false);
  343.       EnableWindow(GetItemHandle(id_TimerFreq),false);
  344.       EnableWindow(GetItemHandle(id_Sound),false);
  345.       EnableWindow(GetItemHandle(id_Minimize),false);
  346.       EnableWindow(GetItemHandle(id_Animate),false);
  347.       EnableWindow(GetItemHandle(id_Spacers),false);
  348.       EnableWindow(GetItemHandle(id_ShakeIt),false);
  349.       EnableWindow(GetItemHandle(id_StopIt),true);
  350.       EnableWindow(GetItemHandle(id_Reset),false);
  351.       EnableWindow(GetItemHandle(id_SaveSettings),false);
  352.       SetFocus(GetItemHandle(id_StopIt));
  353.       if Minimize then Show(sw_ShowMinimized);
  354.     end;
  355.   end { TRattleDlg.ShakeIt };
  356.  
  357. procedure TRattleDlg.StopIt;
  358.   begin
  359.     if Running then begin
  360.       KillTimer(HWindow,1);
  361.       Running := false;
  362.     end;
  363.     dispose(Blocks,Done);
  364.     Blocks := nil;
  365.     { Enable all controls, disable Stop It! button }
  366.     EnableWindow(GetItemHandle(id_BlockSize),true);
  367.     EnableWindow(GetItemHandle(id_BlockCount),true);
  368.     EnableWindow(GetItemHandle(id_TimerFreq),true);
  369.     EnableWindow(GetItemHandle(id_Sound),true);
  370.     EnableWindow(GetItemHandle(id_Minimize),true);
  371.     EnableWindow(GetItemHandle(id_Animate),true);
  372.     EnableWindow(GetItemHandle(id_Spacers),true);
  373.     EnableWindow(GetItemHandle(id_ShakeIt),true);
  374.     EnableWindow(GetItemHandle(id_StopIt),false);
  375.     EnableWindow(GetItemHandle(id_Reset),true);
  376.     EnableWindow(GetItemHandle(id_SaveSettings),true);
  377.     SetFocus(GetItemHandle(id_ShakeIt));
  378.   end { TRattleDlg.StopIt };
  379.  
  380. procedure TRattleDlg.Reset;
  381.   begin
  382.     ResetParams;
  383.   end { TRattleDlg.Reset };
  384.  
  385. procedure TRattleDlg.SaveSettings;
  386. {
  387.   Save the current control settings as the new defaults, and store them
  388.   in the WIN.INI file.  They will be loaded the next time Rattle is
  389.   launched.  The current settings also become the new default settings.
  390. }
  391.   var
  392.     S : TNumStr;
  393.   begin
  394.     if not GetSettings then exit;                    { read the controls }
  395.     StartSettings := Settings;
  396.     with StartSettings do begin
  397.       str(BlockSize,S);
  398.       WriteProfileString(AppName,'BlockSize',S);
  399.       str(BlockCount,S);
  400.       WriteProfileString(AppName,'BlockCount',S);
  401.       str(TimerFreq,S);
  402.       WriteProfileString(AppName,'TimerFreq',S);
  403.       BoolToStr(MakeSound,S);
  404.       WriteProfileString(AppName,'Sound',S);
  405.       BoolToStr(Minimize,S);
  406.       WriteProfileString(AppName,'Minimize',S);
  407.       BoolToStr(Animate,S);
  408.       WriteProfileString(AppName,'Animate',S);
  409.       BoolToStr(Spacers,S);
  410.       WriteProfileString(AppName,'Spacers',S);
  411.     end;
  412.   end { TRattleDlg.SaveSettings };
  413.  
  414. procedure TRattleDlg.ResetParams;
  415. {
  416.   Restore startup settings and update controls.
  417. }
  418.   var
  419.     S : TNumStr;
  420.   begin
  421.     Settings := StartSettings;
  422.     with Settings do begin
  423.       str(BlockSize,S);
  424.       EditBlockSize^.SetText(S);
  425.       str(BlockCount,S);
  426.       EditBlockCount^.SetText(S);
  427.       str(TimerFreq,S);
  428.       EditTimerFreq^.SetText(S);
  429.       if MakeSound then ToggleSound^.Check else ToggleSound^.Uncheck;
  430.       if Minimize then ToggleMinimize^.Check else ToggleMinimize^.Uncheck;
  431.       if Animate then ToggleAnimate^.Check else ToggleAnimate^.Uncheck;
  432.       if Spacers then ToggleSpacers^.Check else ToggleSpacers^.Uncheck;
  433.     end;
  434.   end { TRattleDlg.ResetParams };
  435.  
  436. function TRattleDlg.GetSettings;
  437. {
  438.   Read values from controls and store them in the Settings record.
  439.   Returns false if any numeric values are out of range.
  440. }
  441.   var
  442.     S : TNumStr;
  443.     L : longint;
  444.     E : integer;
  445.     P : PHandle;
  446.   begin
  447.     GetSettings := false;
  448.     with Settings do begin
  449.       EditBlockSize^.GetText(S,sizeof(S));
  450.       val(S,L,E);
  451.       if (E <> 0) or (L < 1) then begin
  452.         Error('Invalid block size');
  453.         SetFocus(EditBlockSize^.HWindow);
  454.         EditBlockSize^.SetSelection(0,strlen(S));
  455.         exit;
  456.       end;
  457.       BlockSize := L;
  458.       EditBlockCount^.GetText(S,sizeof(S));
  459.       val(S,L,E);
  460.       if (E <> 0) or (L < 1) then begin
  461.         Error('Invalid block count');
  462.         SetFocus(EditBlockCount^.HWindow);
  463.         EditBlockCount^.SetSelection(0,strlen(S));
  464.         exit;
  465.       end;
  466.       BlockCount := L;
  467.       EditTimerFreq^.GetText(S,sizeof(S));
  468.       val(S,L,E);
  469.       if (E <> 0) or (L < 0) then begin
  470.         Error('Invalid timer frequency');
  471.         SetFocus(EditTimerFreq^.HWindow);
  472.         EditTimerFreq^.SetSelection(0,strlen(S));
  473.         exit;
  474.       end;
  475.       TimerFreq := L;
  476.       MakeSound := (ToggleSound^.GetCheck = bf_Checked);
  477.       Minimize := (ToggleMinimize^.GetCheck = bf_Checked);
  478.       Animate := (ToggleAnimate^.GetCheck = bf_Checked);
  479.       Spacers := (ToggleSpacers^.GetCheck = bf_Checked);
  480.     end;
  481.     GetSettings := true;
  482.   end { TRattleDlg.GetSettings };
  483.  
  484. procedure TRattleDlg.ReadSettings;
  485. {
  486.   Loads the default program settings from WIN.INI.  If the settings
  487.   cannot be found in WIN.INI, or if the value in WIN.INI is invalid,
  488.   then the startup variables are set to the values originally passed
  489.   in the Init method.
  490. }
  491.   var
  492.     S,
  493.     Def : TNumStr;
  494.     L   : longint;
  495.     E   : integer;
  496.   procedure GetLongSetting(var Long    : longint;
  497.                                KeyName : pchar);
  498.     begin
  499.       str(L,Def);
  500.       GetProfileString(AppName,KeyName,Def,S,sizeof(S));
  501.       val(S,L,E);
  502.       if E = 0 then Long := L;
  503.     end;
  504.   procedure GetBoolSetting(var B       : boolean;
  505.                                KeyName : pchar);
  506.     begin
  507.       BoolToStr(B,Def);
  508.       GetProfileString(AppName,KeyName,Def,S,sizeof(S));
  509.       val(S,L,E);
  510.       if E = 0 then B := (L <> 0);
  511.     end;
  512.   begin
  513.     with StartSettings do begin
  514.       GetLongSetting(BlockSize,'BlockSize');
  515.       GetLongSetting(BlockCount,'BlockCount');
  516.       GetLongSetting(TimerFreq,'TimerFreq');
  517.       GetBoolSetting(MakeSound,'Sound');
  518.       GetBoolSetting(Minimize,'Minimize');
  519.       GetBoolSetting(Animate,'Animate');
  520.       GetBoolSetting(Spacers,'Spacers');
  521.     end;
  522.   end { TRattleDlg.ReadSettings };
  523.  
  524. procedure TRattleDlg.Error;
  525.   begin
  526.     MessageBeep(0);
  527.     MessageBox(HWindow,Msg,'Error',mb_OK or mb_IconExclamation);
  528.   end { TRattleDlg.Error };
  529.  
  530. {-- TBlockCollection Methods --------------------------------------------}
  531.  
  532. procedure TBlockCollection.FreeItem;
  533.   begin
  534.     if Item <> nil then begin
  535.       GlobalUnlock(PHandle(Item)^);
  536.       GlobalFree(PHandle(Item)^);
  537.       dispose(Item);
  538.     end;
  539.   end { TBlockCollection.FreeItem };
  540.  
  541. {-- TAboutDialog Methods ------------------------------------------------}
  542.  
  543. constructor TAboutDialog.Init;
  544.   begin
  545.     TDialog.Init(AParent,AName);
  546.     Blocks := InitBlockCount;
  547.     BlockSize := InitBlockSize;
  548.   end { TAboutDialog.Init };
  549.  
  550. procedure TAboutDialog.SetupWindow;
  551.   var
  552.     Stat    : array[0..60] of char;
  553.     ArgList : array[0..1] of longint;
  554.   begin
  555.     if Blocks <> 0 then
  556.       begin
  557.         ArgList[0] := Blocks;
  558.         ArgList[1] := BlockSize * Blocks;
  559.         wvsprintf(Stat,'%lu blocks (%lu bytes) have been allocated.',ArgList);
  560.       end
  561.     else
  562.       strcopy(Stat,'No memory blocks allocated.');
  563.     SetWindowText(GetItemHandle(id_Status),Stat);
  564.   end { TAboutDialog.SetupWindow };
  565.  
  566. {-- TMyApp Methods ------------------------------------------------------}
  567.  
  568. procedure TMyApp.InitMainWindow;
  569.   begin
  570.     MainWindow := New(PRattleDlg,Init(nil,AppName,DefSettings));
  571.   end { TMyApp.InitMainWindow };
  572.  
  573. {-- Main Program --------------------------------------------------------}
  574.  
  575. var
  576.   MyApp : TMyApp;
  577.  
  578. begin
  579.   MyApp.Init(AppName);
  580.   MyApp.Run;
  581.   MyApp.Done;
  582. end.
  583.